package com.javaforever.lightwing.gui;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;

import org.javaforever.gatescore.core.FileCopyer;
import org.javaforever.gatescore.core.FrontPrism;
import org.javaforever.gatescore.vue.DevEnvJs;
import org.javaforever.gatescore.vue.ElementUIHomePage;
import org.javaforever.gatescore.vue.EnJs;
import org.javaforever.gatescore.vue.ProdEnvJs;
import org.javaforever.gatescore.vue.SitEnvJs;
import org.javaforever.gatescore.vue.VuePageVars;
import org.javaforever.gatescore.vue.VueRouter;
import org.light.domain.Domain;
import org.light.domain.Independent;
import org.light.domain.IndependentConfig;
import org.light.domain.ManyToMany;
import org.light.domain.Prism;
import org.light.domain.Project;
import org.light.domain.Util;
import org.light.domain.ValidateInfo;
import org.light.exception.ValidateException;
import org.light.generator.DBDefinitionGenerator;
import org.light.generator.MysqlTwoDomainsDBDefinitionGenerator;
import org.light.oracle.core.OraclePrism;
import org.light.oracle.generator.Oracle11gSqlReflector;
import org.light.utils.SqlReflector;
import org.light.utils.StringUtil;

public class JarBackendProjectExportUtil {
	public static void generateProjectFiles(Project project, boolean ignoreWarning) throws Exception {
		if (project.getDbType() == null || "".equals(project.getDbType())
				|| "mysql".equalsIgnoreCase(project.getDbType()) || "mariadb".equalsIgnoreCase(project.getDbType())) {
			ValidateInfo info = project.validate(ignoreWarning);
			if (info.success(ignoreWarning) == false) {
				throw new ValidateException(info);
			}
			try {
				project.decorateMentuItems();
				String srcfolderPath = project.getProjectFolderPath();
				if ("normal".equalsIgnoreCase(project.getSchema())) {
					for (Prism ps : project.getPrisms()) {
						ps.setFolderPath(project.getProjectFolderPath());
						ps.generatePrismFiles(ignoreWarning);
					}
					for (Util u : project.getUtils()) {
						String utilPath = project.getProjectFolderPath() + "src/main/java/"
								+ project.packagetokenToFolder(u.getPackageToken()) + "utils/";
						writeToFile(utilPath + u.getFileName(), u.generateUtilString());
					}

					for (Independent idt : project.getIndependents()) {
						String idtPath = project.getProjectFolderPath() + "src/main/java/"
								+ project.packagetokenToFolder(idt.getPackageToken());
						writeToFile(idtPath + idt.getFileName(), idt.generateImplString());
					}

					String homePath = project.getProjectFolderPath() + "src/main/resources/static/";
					writeToFile(homePath + "index.html", project.getJumphomepage().generateIncludeString());

					homePath = project.getProjectFolderPath() + "src/main/resources/static/pages/";
					writeToFile(homePath + "index.html", project.getHomepage().generateStatementList().getContent());

					FileCopyer copy = new FileCopyer();

					if (!StringUtil.isBlank(project.getExcelTemplateName())) {
						File mF1 = new File(
								(project.getExcelTemplateFolder() + project.getExcelTemplateName()).replace("\\", "/"));
						File mF2 = new File(
								(project.getProjectFolderPath() + "exceltemplate/" + project.getExcelTemplateName())
										.replace("\\", "/"));
						if (mF1.exists()) {
							if (!mF2.getParentFile().exists()) {
								mF2.getParentFile().mkdirs();
							}
							if (!mF2.exists()) {
								mF2.createNewFile();
							}
							copy.copy(mF1.getPath(), mF2.getPath());
						}
					}

					for (IndependentConfig idc : project.getIndependentConfigs()) {
						writeToFile(project.getProjectFolderPath() + idc.getFolder() + idc.getFileName(),
								idc.generateImplString());
					}

					StringBuilder sql = new StringBuilder();
					boolean createNew = true;
					for (DBDefinitionGenerator dbd : project.getDbDefinitionGenerators()) {
						sql.append(dbd.generateDBSql(createNew)).append("\n");
						if (createNew)
							createNew = false;
					}
					for (MysqlTwoDomainsDBDefinitionGenerator mtg : project.getMyTwoDBGenerators()) {
						sql.append(mtg.generateDBSql(project.getDbType()));
					}

					for (List<Domain> dataDomains : project.getDataDomains()) {
						sql.append("\n");
						for (Domain d : dataDomains) {
							sql.append(SqlReflector.generateInsertSqlWithValue(d)).append("\n");
						}

						for (Domain d : dataDomains) {
							for (ManyToMany mtm : d.getManyToManies()) {
								sql.append(SqlReflector.generateMtmInsertSqlWithValues(mtm)).append("\n");
							}
						}
					}

					writeToFile(project.getProjectFolderPath() + "sql/" + project.getStandardName() + ".sql",
							sql.toString());
					TemplatesResourceCopyer tcopy = new TemplatesResourceCopyer();
					tcopy.downloadUnpackBackEndTemplates(project.getFolderPath()+project.getStandardName()+"/",false);
				} else if ("dbtools".equalsIgnoreCase(project.getSchema())) {
					StringBuilder sql = new StringBuilder();
					boolean createNew = true;
					for (DBDefinitionGenerator dbd : project.getDbDefinitionGenerators()) {
						sql.append(dbd.generateDBSql(createNew)).append("\n");
						if (createNew)
							createNew = false;
					}
					for (MysqlTwoDomainsDBDefinitionGenerator mtg : project.getMyTwoDBGenerators()) {
						sql.append(mtg.generateDBSql(project.getDbType()));
					}

					for (List<Domain> dataDomains : project.getDataDomains()) {
						sql.append("\n");
						for (Domain d : dataDomains) {
							sql.append(SqlReflector.generateInsertSqlWithValue(d)).append("\n");
						}

						for (Domain d : dataDomains) {
							for (ManyToMany mtm : d.getManyToManies()) {
								sql.append(SqlReflector.generateMtmInsertSqlWithValues(mtm)).append("\n");
							}
						}
					}

					for (List<Domain> dataDomains : project.getDataDomains()) {
						sql.append("\n");
						for (Domain d : dataDomains) {
							if (d.hasDomainId())
								sql.append(SqlReflector.generateUpdateSqlWithValue(d)).append("\n");
						}
					}

					for (List<Domain> dataDomains : project.getDataDomains()) {
						sql.append("\n");
						for (Domain d : dataDomains) {
							if (d.hasDomainId())
								sql.append(SqlReflector.generateDeleteSqlWithValue(d)).append("\n");
						}

						for (Domain d : dataDomains) {
							for (ManyToMany mtm : d.getManyToManies()) {
								sql.append(SqlReflector.generateMtmDeleteSqlWithValues(mtm)).append("\n");
							}
						}
					}

					sql.append("\n");
					for (DBDefinitionGenerator dbd : project.getDbDefinitionGenerators()) {
						sql.append(dbd.generateDropTableSqls(false)).append("\n");
					}

					for (MysqlTwoDomainsDBDefinitionGenerator mtg : project.getMyTwoDBGenerators()) {
						sql.append(mtg.generateDropLinkTableSql());
					}

					writeToFile(project.getProjectFolderPath() + "sql/" + project.getStandardName() + ".sql",
							sql.toString());

					FileCopyer copy = new FileCopyer();
					if (!StringUtil.isBlank(project.getExcelTemplateName())) {
						File mF1 = new File(
								(project.getExcelTemplateFolder() + project.getExcelTemplateName()).replace("\\", "/"));
						File mF2 = new File(
								(project.getProjectFolderPath() + "exceltemplate/" + project.getExcelTemplateName())
										.replace("\\", "/"));
						if (mF1.exists()) {
							if (!mF2.getParentFile().exists()) {
								mF2.getParentFile().mkdirs();
							}
							if (!mF2.exists()) {
								mF2.createNewFile();
							}
							copy.copy(mF1.getPath(), mF2.getPath());
						}
					} 		
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw e;
			}
		} else if ("oracle".equals(project.getDbType())) {
			ValidateInfo info = project.validate(ignoreWarning);
			if (info.success(ignoreWarning) == false) {
				for (String s : info.getCompileErrors()) {
					System.out.println(s);
				}
				return;
			}
			try {
				project.decorateMentuItems();
				String projectFolderPath = project.getProjectFolderPath().replace('\\', '/');
				String templateFolderPath = project.getSourceFolderPath().replace('\\', '/');
				if ("normal".equalsIgnoreCase(project.getSchema())) {
					if (project.getSgsSource() != null && !project.getSgsSource().equals("")) {
						writeToFile(projectFolderPath + "sgs/" + StringUtil.capFirst(project.getStandardName())
								+ "_original.sgs", project.getSgsSource());
					}
					for (Prism ps : project.getPrisms()) {
						OraclePrism ops = (OraclePrism) ps;
						ops.setFolderPath(projectFolderPath);
						ops.generatePrismFiles(ignoreWarning);
					}
					for (Util u : project.getUtils()) {
						String utilPath = projectFolderPath + "src/main/java/"
								+ project.packagetokenToFolder(u.getPackageToken()) + "utils/";
						writeToFile(utilPath + u.getFileName(), u.generateUtilString());
					}
					for (Independent idt : project.getIndependents()) {
						String idtPath = project.getProjectFolderPath() + "src/main/java/"
								+ project.packagetokenToFolder(idt.getPackageToken());
						writeToFile(idtPath + idt.getFileName(), idt.generateImplString());
					}

					String homePath = projectFolderPath + "src/main/resources/static/";
					writeToFile(homePath + "index.html", project.getJumphomepage().generateIncludeString());

					homePath = projectFolderPath + "src/main/resources/static/pages/";
					project.getHomepage().setTitle(project.getTitle());
					project.getHomepage().setSubTitle(project.getSubTitle());
					project.getHomepage().setFooter(project.getFolderPath());
					project.getHomepage().setResolution(project.getResolution());
					writeToFile(homePath + "index.html", project.getHomepage().generateStatementList().getContent());

					FileCopyer copy = new FileCopyer();

					if (!StringUtil.isBlank(project.getExcelTemplateName())) {
						File mF1 = new File(
								(project.getExcelTemplateFolder() + project.getExcelTemplateName()).replace("\\", "/"));
						File mF2 = new File((projectFolderPath + "exceltemplate/" + project.getExcelTemplateName())
								.replace("\\", "/"));
						if (mF1.exists()) {
							if (!mF2.getParentFile().exists()) {
								mF2.getParentFile().mkdirs();
							}
							if (!mF2.exists()) {
								mF2.createNewFile();
							}
							copy.copy(mF1.getPath(), mF2.getPath());
						}
					}

					for (IndependentConfig idc : project.getIndependentConfigs()) {
						writeToFile(project.getProjectFolderPath() + idc.getFolder() + idc.getFileName(),
								idc.generateImplString());
					}

					StringBuilder sql = new StringBuilder();
					boolean createNew = false;
					for (DBDefinitionGenerator dbd : project.getDbDefinitionGenerators()) {
						sql.append(dbd.generateDropTableSqls(createNew));
					}

					for (MysqlTwoDomainsDBDefinitionGenerator mtg : project.getMyTwoDBGenerators()) {
						sql.append(mtg.generateOracleDropLinkTableSql());
					}

					sql.append("\n\n");

					sql.append("drop sequence COMMONSEQUENCE;").append("\n\n");
					sql.append("-- Create sequence").append("\n").append("create sequence COMMONSEQUENCE").append("\n")
							.append("minvalue 10000").append("\n").append("maxvalue 9999999999999999999999999999")
							.append("\n").append("start with 10000").append("\n").append("increment by 1").append("\n")
							.append("cache 20;").append("\n\n");

					for (DBDefinitionGenerator dbd : project.getDbDefinitionGenerators()) {
						sql.append(dbd.generateDBSql(createNew)).append("\n");
					}
					for (MysqlTwoDomainsDBDefinitionGenerator mtg : project.getMyTwoDBGenerators()) {
						sql.append(mtg.generateDBSql(project.getDbType()));
					}

					// load initial data
					for (List<Domain> dataDomains : project.getDataDomains()) {
						sql.append("\n");
						for (Domain d : dataDomains) {
							sql.append(Oracle11gSqlReflector.generateInsertSqlWithValue(d)).append("\n");
						}

						for (Domain d : dataDomains) {
							for (ManyToMany mtm : d.getManyToManies()) {
								sql.append(Oracle11gSqlReflector.generateMtmInsertSqlWithValues(mtm)).append("\n");
							}
						}
					}
					sql.append("commit;\n");
					writeToFile(projectFolderPath + "sql/" + project.getStandardName() + ".sql", sql.toString());
					
					TemplatesResourceCopyer tcopy = new TemplatesResourceCopyer();
					tcopy.downloadUnpackBackEndTemplates(project.getFolderPath()+project.getStandardName()+"/",true);
				} else if ("dbtools".equalsIgnoreCase(project.getSchema())) {
					StringBuilder sql = new StringBuilder();
					boolean createNew = false;
					for (DBDefinitionGenerator dbd : project.getDbDefinitionGenerators()) {
						sql.append(dbd.generateDropTableSqls(createNew));
					}

					for (MysqlTwoDomainsDBDefinitionGenerator mtg : project.getMyTwoDBGenerators()) {
						sql.append(mtg.generateOracleDropLinkTableSql());
					}

					sql.append("\n\n");

					sql.append("drop sequence COMMONSEQUENCE;").append("\n\n");
					sql.append("-- Create sequence").append("\n").append("create sequence COMMONSEQUENCE").append("\n")
							.append("minvalue 10000").append("\n").append("maxvalue 9999999999999999999999999999")
							.append("\n").append("start with 10000").append("\n").append("increment by 1").append("\n")
							.append("cache 20;").append("\n\n");

					for (DBDefinitionGenerator dbd : project.getDbDefinitionGenerators()) {
						sql.append(dbd.generateDBSql(createNew)).append("\n");
					}
					for (MysqlTwoDomainsDBDefinitionGenerator mtg : project.getMyTwoDBGenerators()) {
						sql.append(mtg.generateDBSql(project.getDbType()));
					}

					// load initial data
					for (List<Domain> dataDomains : project.getDataDomains()) {
						sql.append("\n");
						for (Domain d : dataDomains) {
							sql.append(Oracle11gSqlReflector.generateInsertSqlWithValue(d)).append("\n");
						}

						for (Domain d : dataDomains) {
							for (ManyToMany mtm : d.getManyToManies()) {
								sql.append(Oracle11gSqlReflector.generateMtmInsertSqlWithValues(mtm)).append("\n");
							}
						}
					}

					for (List<Domain> dataDomains : project.getDataDomains()) {
						sql.append("\n");
						for (Domain d : dataDomains) {
							sql.append(Oracle11gSqlReflector.generateUpdateSqlWithValue(d)).append("\n");
						}
					}

					for (List<Domain> dataDomains : project.getDataDomains()) {
						sql.append("\n");
						for (Domain d : dataDomains) {
							sql.append(Oracle11gSqlReflector.generateDeleteSqlWithValue(d)).append("\n");
						}

						for (Domain d : dataDomains) {
							for (ManyToMany mtm : d.getManyToManies()) {
								sql.append(SqlReflector.generateMtmDeleteSqlWithValues(mtm)).append("\n");
							}
						}
					}

					sql.append("commit;\n");
					writeToFile(project.getProjectFolderPath() + "sql/" + project.getStandardName() + ".sql", sql.toString());

					FileCopyer copy = new FileCopyer();
					if (!StringUtil.isBlank(project.getExcelTemplateName())) {
						File mF1 = new File(
								(project.getExcelTemplateFolder() + project.getExcelTemplateName()).replace("\\", "/"));
						File mF2 = new File(
								(project.getProjectFolderPath() + "exceltemplate/" + project.getExcelTemplateName())
										.replace("\\", "/"));
						if (mF1.exists()) {
							if (!mF2.getParentFile().exists()) {
								mF2.getParentFile().mkdirs();
							}
							if (!mF2.exists()) {
								mF2.createNewFile();
							}
							copy.copy(mF1.getPath(), mF2.getPath());
						}
					}				
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw e;
			}
		} else {
			ValidateInfo info = new ValidateInfo();
			info.addCompileError("未支持项目所用数据库。");
			throw new ValidateException(info);
		}
	}

	public static boolean delAllFile(String path) {
		boolean flag = false;
		File file = new File(path);
		if (!file.exists()) {
			return flag;
		}
		if (!file.isDirectory()) {
			return flag;
		}
		String[] tempList = file.list();
		File temp = null;
		for (int i = 0; i < tempList.length; i++) {
			if (path.endsWith(File.separator)) {
				temp = new File(path + tempList[i]);
			} else {
				temp = new File(path + File.separator + tempList[i]);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
				delFolder(path + "/" + tempList[i]);// 再删除空文件夹
				flag = true;
			}
		}
		return flag;
	}

	public static void delFolder(String folderPath) {
		try {
			delAllFile(folderPath); // 删除完里面所有内容
			String filePath = folderPath;
			filePath = filePath.toString();
			java.io.File myFilePath = new java.io.File(filePath);
			myFilePath.delete(); // 删除空文件夹
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void generateProjectZip(Project project, boolean ignoreWarning) throws Exception {
		String rootFolder = project.getFolderPath();
		rootFolder = rootFolder.replace("\\", "/");
		String zipFolder = rootFolder;
		if (rootFolder.contains("/")) {
			zipFolder = rootFolder.substring(0, rootFolder.lastIndexOf("/"));
			zipFolder = zipFolder + "/" + project.getStandardName() + "/";
		} else {
			throw new ValidateException("输出文件夹错误");
		}
		project.setFolderPath(rootFolder);

		delAllFile(project.getFolderPath() + project.getStandardName() + ".zip");
		delFolder(zipFolder);
		File f = new File(zipFolder);
		if (!f.getParentFile().exists()) {
			f.getParentFile().mkdirs();
		}
		f.mkdirs();

		generateProjectFiles(project, ignoreWarning);
		ZipCompressor compressor = new ZipCompressor(rootFolder + project.getStandardName() + ".zip");
		compressor.compressExe(zipFolder);
		delFolder(zipFolder);
	}

	public static void writeToFile(String filePath, String content) throws Exception {
		File f = new File(filePath);
		if (!f.getParentFile().exists()) {
			f.getParentFile().mkdirs();
		}
		f.createNewFile();
		try (Writer fw = new BufferedWriter(
				new OutputStreamWriter(new FileOutputStream(f.getAbsolutePath()), "UTF-8"))) {
			fw.write(content, 0, content.length());
		}
	}

}
